package com.cy.module.dingtalk;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cy.BasicController;
import com.cy.ext.plugin.route.ControllerBind;
import com.cy.model.Account;
import com.cy.model.Menu;
import com.cy.model.dingtalk.AccountMapDingding;
import com.cy.shiro.DingTalkUserToken;
import com.cy.utils.PropertyUtil;
import com.cy.utils.dingtalk.DingTalkEncryptException;
import com.cy.utils.dingtalk.DingTalkEncryptor;
import com.cy.utils.dingtalk.DingTalkUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;

import javax.servlet.ServletInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 钉钉接口相关
 */
@ControllerBind(controllerKey = "/dingtalk")
public class DingTalkController extends BasicController {

    public void getCallback(){
        JSONObject callback = DingTalkUtils.getCallback();
        renderJson(callback != null ? callback: "null");
    }

    public void deleteCallback(){
        renderJson(DingTalkUtils.deleteCallback());
    }

    public void registerCallback(){
        renderJson(DingTalkUtils.registerCallback());
    }

    public void updateTicket(){
        renderText(DingTalkUtils.updateTicket());
    }

    /**
     * 获取和钉钉匹配的用户
     */
    public void getMatchUser(){
        Account loginAccount = getLoginAccount();
        String mobile = loginAccount.getMobile();
        String email = loginAccount.getEmail();
        Set<JSONObject> allUsers = DingTalkUtils.getAllUsers();
        for (JSONObject user : allUsers){
            //匹配和钉钉用户mobile或email对应的用户
            if (StringUtils.isNotBlank(mobile) && mobile.equals(user.getString("mobile"))){
                renderJson(user);
                return;
            }
            if (StringUtils.isNotBlank(email) && email.equals(user.getString("email"))){
                renderJson(user);
                return;
            }
        }
        renderJson("{}");
    }

    /**
     * 钉钉和CCRM用户绑定
     */
    public void bindUser(){
        String dingUserId = getPara("dingUserId");
        Account loginAccount = getLoginAccount();
        AccountMapDingding amd = new AccountMapDingding();
        try {
            amd.setAccountId(loginAccount.getAccountId());
            amd.setDingUserId(dingUserId);
            amd.setCreateTime(new Date());
            amd.save();
            renderSuccess();
        } catch (Exception e){
            e.printStackTrace();
            renderFail("绑定失败，请检查该用户手机号或E-Mail是否已被其他用户使用!");
        }
    }

    /**
     * 钉钉回调接口，由钉钉API调用
     */
    public void eventCallback(){
        /**url中的签名**/
        String msgSignature = getPara("signature");
        /**url中的时间戳**/
        String timeStamp = getPara("timestamp");
        /**url中的随机字符串**/
        String nonce = getPara("nonce");

        /**post数据包数据中的加密数据**/
        ServletInputStream sis;
        StringBuilder sb = new StringBuilder();
        try {
            sis = getRequest().getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(sis));
            String line;
            while((line = br.readLine())!=null){
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        JSONObject jsonEncrypt = JSONObject.parseObject(sb.toString());
        String encrypt = jsonEncrypt.getString("encrypt");

        /**对encrypt进行解密**/
        DingTalkEncryptor dingTalkEncryptor;
        String plainText;
        try {
            //对于DingTalkEncryptor的第三个参数，ISV进行配置的时候传对应套件的SUITE_KEY，普通企业传Corpid
            dingTalkEncryptor = new DingTalkEncryptor(DingTalkUtils.TOKEN, DingTalkUtils.ENCODING_AES_KEY, DingTalkUtils.CORP_ID);
            plainText = dingTalkEncryptor.getDecryptMsg(msgSignature, timeStamp, nonce, encrypt);
        } catch (DingTalkEncryptException e) {
            e.printStackTrace();
            renderJson();
            return;
        }

        /**对从encrypt解密出来的明文进行处理**/
        JSONObject plainTextJson = JSONObject.parseObject(plainText);
        String eventType = plainTextJson.getString("EventType");
        System.out.println("============="+ eventType + " : " + plainTextJson);
        switch (eventType){
            case "user_add_org"://通讯录用户增加
                userAddOrg(plainTextJson);
                break;
            case "user_modify_org"://通讯录用户更改
                userModifyOrg(plainTextJson);
                break;
            case "user_leave_org"://通讯录用户离职
                userLeaveOrg(plainTextJson);
                break;
            /*case "org_admin_add"://通讯录用户被设为管理员
                break;
            case "org_admin_remove"://通讯录用户被取消设置管理员
                break;
            case "org_dept_create"://通讯录企业部门创建
                break;
            case "org_dept_modify"://通讯录企业部门修改
                break;
            case "org_dept_remove"://通讯录企业部门删除
                break;
            case "org_remove"://企业被解散
                break;
            case "chat_add_member"://群会话添加人员
                break;
            case "chat_remove_member"://群会话删除人员
                break;
            case "chat_quit"://群会话用户主动退群
                break;
            case "chat_update_owner"://群会话更换群主
                break;
            case "chat_update_title"://群会话更换群名称
                break;
            case "chat_disband"://群会话解散群
                break;
            case "chat_disband_microapp"://绑定了微应用的群会话，在解散时回调
                break;*/
            case "check_url"://第一次注册回调接口的检测
            default :
                break;
        }

        /**对返回信息进行加密**/
        long timeStampLong = Long.parseLong(timeStamp);
        Map<String,String> jsonMap;
        try {
            jsonMap = dingTalkEncryptor.getEncryptedMap("success", timeStampLong, nonce);
        } catch (DingTalkEncryptException e) {
            e.printStackTrace();
            renderJson();
            return;
        }
        JSONObject json = new JSONObject();
        json.putAll(jsonMap);
        renderJson(json.toString());
    }

    /**
     *  通信录用户增加
     */
    private boolean userAddOrg(JSONObject json){
        JSONArray userIds = json.getJSONArray("UserId");
        try {
            for (Object userId : userIds){
                JSONObject user = DingTalkUtils.getUserById(userId.toString());
                Account account = new Account();
                String mobile = user.getString("mobile");
                account.setAccount(mobile);
                //默认手机号后6位为密码
                account.setPassword(mobile.substring(5));
                account.setEmail(user.getString("email"));
                account.setName(user.getString("name"));
                account.setRemark(user.getString("remark"));
                account.setJobNo(user.getString("jobnumber"));
                account.setMobile(mobile);
                account.setLevel(1);
                account.setStatus(1);
                Date now = new Date();
                account.setCreateTime(now);
                if (account.save()){
                    //钉钉用户和平台账号绑定
                    AccountMapDingding amd = new AccountMapDingding();
                    amd.setAccountId(account.getAccountId());
                    amd.setDingUserId(userId.toString());
                    amd.setCreateTime(now);
                    amd.save();
                }
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     *  通信录用户修改
     */
    private boolean userModifyOrg(JSONObject json){
        JSONArray userIds = json.getJSONArray("UserId");
        try {
            for (Object userId : userIds){
                JSONObject user = DingTalkUtils.getUserById(userId.toString());
                Account account = Account.dao.findByDingUserId(userId.toString());
                account.setEmail(user.getString("email"));
                account.setName(user.getString("name"));
                account.setRemark(user.getString("remark"));
                account.setMobile(user.getString("mobile"));
                account.setJobNo(user.getString("jobnumber"));
                account.update();
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     *  通信录用户离职
     */
    private boolean userLeaveOrg(JSONObject json){
        JSONArray userIds = json.getJSONArray("UserId");
        try {
            for (Object userId : userIds){
                Account account = Account.dao.findByDingUserId(userId.toString());
                account.setStatus(2);//2代表离职
                account.update();
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 钉钉微应用主页
     */
    public void appIndex(){
        setAttr("appid", DingTalkUtils.CORP_ID);
        setAttr("auth_url", DingTalkUtils.AUTHORIZE_IF);
        setAttr("redirect_uri", PropertyUtil.getGrosseValue(PropertyUtil.KERNEL, "dingTalkLoginCallback"));
        renderJsp("/view/dingtalk/dingtalk-login.jsp");
    }

    /**
     * 钉钉账号登录CCRM
     */
    public void goLogin(){
        String code = getPara("code");
        if (StringUtils.isNotBlank(code)){
            JSONObject loginedUser = DingTalkUtils.getLoginedUser(code);
            if (loginedUser != null){
                String dingUserId = loginedUser.getString("userid");
                Subject subject = SecurityUtils.getSubject();
                DingTalkUserToken token = new DingTalkUserToken(dingUserId);
                token.setExtras(loginedUser);
                try {
                    subject.login(token);
                    redirect("/dingtalk/goIndex");
                    return;
                } catch (AuthenticationException e){
                    renderHtml("<h2>未绑定CCRM账号</h2><br><span style='color: #ff0000'>确保CCRM账号的手机号码或者邮箱与钉钉用户一致后请登录CCRM，系统将自动绑定。<span>");
                    return;
                }
            } else {
                renderHtml("<h2>钉钉未登录</h2>");
                return;
            }
        }
        renderHtml("<h2>code不存在</h2>");
    }

    public void goIndex(){
        Account account = getLoginAccount();
        String viewPath;
        List<Menu> menus;
        String header = getRequest().getHeader("User-Agent");
        if (header.indexOf("Mobile") != -1){//手机端
            menus = account.getDingShowMenus(Menu.Type.DINGTALK_MOBILITY);
            viewPath = "/view/dingtalk/mobility/ding-app-index.jsp";
        } else {//PC端
            menus = account.getDingShowMenus(Menu.Type.DINGTALK_PC);
            viewPath = "/view/dingtalk/pc/ding-app-index.jsp";
        }
        for (Menu menu : menus){
            String url = menu.getUrl();
            if (StringUtils.isNotBlank(url)){
                int i = url.lastIndexOf("/");
                int j = url.lastIndexOf(".");
                String picName = url.substring(i, j);
                menu.put("pic", picName +".png");
            }
        }
        setAttr("menus", menus);
        setAttr("config", DingTalkUtils.getJsapiConfig(getRequest()));
        renderJsp(viewPath);
    }

    /**
     * 扫码登录CCRM
     */
    public void qrCodeLogin(){
        String code = getPara("code");
        if (StringUtils.isNotBlank(code)){
            JSONObject loginedUser = DingTalkUtils.getLoginedUserOfQrCode(code);
            if (loginedUser != null){
                JSONObject userInfo = loginedUser.getJSONObject("user_info");
                String userId = DingTalkUtils.getUseridByUnionid(userInfo.getString("unionid"));
                if (userId == null){
                    renderHtml("<h2>unionid不存在</h2>");
                    return;
                }
                Subject subject = SecurityUtils.getSubject();
                DingTalkUserToken token = new DingTalkUserToken(userId);
                token.setExtras(loginedUser);
                try {
                    subject.login(token);
                    redirect("/clmp/main");
                    return;
                } catch (AuthenticationException e){
                    renderHtml("<h2>未绑定CCRM账号</h2><br><span style='color: #ff0000'>确保CCRM账号的手机号码或者邮箱与钉钉用户一致后请登录CCRM，系统将自动绑定。<span>");
                    return;
                }
            } else {
                renderHtml("<h2>钉钉未登录</h2>");
                return;
            }
        }
        renderHtml("<h2>code不存在</h2>");
    }

}
